package com.jtexplorer.utils;

import com.github.s7connector.api.DaveArea;
import com.github.s7connector.api.S7Connector;
import com.github.s7connector.api.S7Serializer;
import com.github.s7connector.api.factory.S7ConnectorFactory;
import com.github.s7connector.api.factory.S7SerializerFactory;

import java.io.IOException;

public class S7ConnectUti {

    /**
     * 初始化PLC连接
     */
    public S7Connector initConnect(){
        //PLC地址
        String ipAddress = "127.0.0.1";
        //默认端口
        S7Connector s7Connector =  S7ConnectorFactory
                .buildTCPConnector()
                .withHost(ipAddress)
                .withPort(102)
                .withTimeout(10000) //连接超时时间
                .withRack(0)
                .withSlot(1)
                .build();
        S7Serializer s7Serializer2L = S7SerializerFactory.buildSerializer(s7Connector);
        return s7Connector;

    }


    /**
     * 读取PLC中的数据，字符串类型
     *
     **/
    public void readPlcData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB地址，若plc中是DB1000，则填1000
        //第三个参数：数据长度， <=plc中两个偏移量的间隔，当前偏移量为1000，下一个地址偏移量为1100，则长度可填 0-1000；
        //第三个参数：偏移量
        byte[] barcodeByte = s7Connector.read(DaveArea.DB, 1000, 2, 0);
        //由于当前PLC地址中保存的数据类型是字符串类型，所以直接将byte[] 转成string即可；
        String barcode = new String(barcodeByte);
        System.out.println(barcode);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取PLC中的数据
     *
     **/
    public void readPlcDataWord() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB地址，若plc中是DB1000，则填1000
        //第三个参数：数据长度， <=plc中两个偏移量的间隔，当前偏移量为1000，下一个地址偏移量为1100，则长度可填 0-1000；
        //第四个参数：偏移量
        byte[] barcodeByte = s7Connector.read(DaveArea.DB, 1000, 2, 0);
        //由于当前PLC地址中保存的数据类型是字符串类型，所以直接将byte[] 转成string即可；
        String barcode =byteToHex(barcodeByte);
        System.out.println(barcode);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * byte数组转hex
     * @param bytes
     * @return
     */
    public static String byteToHex(byte[] bytes){
        String strHex = "";
        StringBuilder sb = new StringBuilder("");
        for (int n = 0; n < bytes.length; n++) {
            strHex = Integer.toHexString(bytes[n] & 0xFF);
            sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示，位数不够，高位补0
        }
        return sb.toString().trim();
    }

    /**
     * 向PLC中写数据
     *
     **/
    public void writePlcData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB地址，若plc中是DB1000，则填1000
        //第三个参数：偏移量
        //第四个参数：写入的数据 二进制数组byte[],由于plc中地址的数据类型是word，所以写入的数据必须是4位的16进制数据
        s7Connector.write(DaveArea.DB,1000, 4,hexStringToBytes("0001"));

        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 功能： 十六进制字符串转字节数组
     * @param hexString 十六进制字符串
     * @return 字节数组
     */
    public static byte[] hexStringToBytes(String hexString){
        //判空
        if(hexString == null || hexString.length() == 0) {
            return null;
        }

        //合法性校验
        if(!hexString.matches("[a-fA-F0-9]*") || hexString.length() % 2 != 0) {
            return null;
        }

        //计算
        int mid = hexString.length() / 2;
        byte[]bytes = new byte[mid];
        for (int i = 0; i < mid; i++) {
            bytes[i] = Integer.valueOf(hexString.substring(i * 2, i * 2 + 2), 16).byteValue();
        }

        return bytes;
    }


}
